package com.csthink.common.infrastructure.util;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.i18n.LocaleContextHolder;

import java.nio.charset.StandardCharsets;
import java.util.Locale;
import java.util.regex.Matcher;

import static com.csthink.common.infrastructure.constant.Constants.AUDIT_LOGGING_PATTERN_DETAIL_KEYWORD;

/**
 * @author <a href="mailto:security.2009@live.cn">Mars</a>
 * @since 2023-09-12
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Slf4j
public class I18nUtil {

    private static MessageSource messageSource = null;

    public static String formatDisplayName(String firstName, String lastName) {

        String first = (firstName == null ? "" : firstName);
        String last = (lastName == null ? "" : lastName);

        first = first.trim();
        last = last.trim();

        if (last.length() == 0) {
            return first;
        }

        if (first.length() == 0) {
            return last;
        }

        String result = first + " " + last;
        //128 is the max length of DB field
        result = result.length() > 128 ? result.substring(0, 128) : result;
        return result;
    }

    public static boolean containsAsianCharacter(String str) {
        if (str == null) {
            return false;
        }

        return str.length() != str.getBytes(StandardCharsets.UTF_8).length;
    }

    public static boolean endsWithAsianCharacter(String str) {
        return containsAsianCharacter(str.substring(str.length() - 1));
    }

    public static boolean startsWithAsianCharacter(String str) {
        return containsAsianCharacter(str.substring(0, 1));
    }

    public static String formatDisplayNameLN(String firstName, String lastName) {
        String first = (firstName == null ? "" : firstName);
        String last = (lastName == null ? "" : lastName);

        first = first.trim();
        last = last.trim();

        if (last.length() == 0) {
            return first;
        }

        if (first.length() == 0) {
            return last;
        }

        if (containsAsianCharacter(first) || containsAsianCharacter(last)) {
            if (endsWithAsianCharacter(last) || startsWithAsianCharacter(first)) {
                return last + first;
            } else {
                return last + " " + first;
            }
        } else {
            return first + " " + last;
        }
    }

    public static String getHttpStatusMessage(String key) {
        return getMessage("error." + key, null);
    }

    public static String getMessage(String key) {
        return getMessage(key, null);
    }

    public static String getMessage(String key, Object[] params) {

        return getMessage(key, params, LocaleContextHolder.getLocale());
    }

    public static String getMessage(String key, Object[] params, Locale locale) {
        try {
            if (locale != null && "ts".equals(locale.getLanguage())) {
                locale = new Locale("en", "US");
                return "(pseudo)_" + getMessageSource().getMessage(key, params, locale);
            }
            return getMessageSource().getMessage(key, params, locale);
        } catch (NoSuchMessageException e) {
            log.warn("No such message source: " + key);
            return "";
        }
    }

    private static MessageSource getMessageSource() {
        if (messageSource == null) {
            messageSource = SpringUtil.getBean(MessageSource.class);
        }
        return messageSource;
    }

    public static String getTimeZoneName(String key) {
        return getMessageWithPrefix("tz.", key);
    }

    public static String getLanguageName(String languageID) {
        return getMessageWithPrefix("language.", languageID);
    }

    public static String getCountryName(String key) {
        return getMessageWithPrefix("country.", key);
    }

    public static String getMessageWithPrefix(String prefix, String key) {
        String value = getMessage(prefix + key, null);
        if (StringUtils.isEmpty(value)) {
            value = key;
        }
        return value;
    }

    /*
     *
     * Onlu support following language format: fr-FR
     */
    public static Locale getLocaleByLanguage(String language) {
        if (StringUtils.isEmpty(language) || !StringUtils.contains(language, "-")) {
            return Locale.ENGLISH;
        }
        String[] languages = language.trim().split("-");
        if (languages.length > 1) {
            return new Locale(languages[0], languages[1]);
        }
        return Locale.ENGLISH;
    }


    public static String getLocaleContent(String content) {
        if(StringUtils.isEmpty(content)) {
            return content;
        }
        Matcher m = AUDIT_LOGGING_PATTERN_DETAIL_KEYWORD.matcher(content);
        while (m.find()) {
            String str = m.group();
            String message = str.substring(2, str.length() - 2);

            var msg = I18nUtil.getMessage(message);
            content = content.replace(str, msg);
        }
        return content;
    }
}
